home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / TCL1 / TCLOPT.TXT < prev   
Text File  |  1990-08-04  |  6KB  |  162 lines

  1. Improvements to the THINK Class Library
  2. =======================================
  3. I recently helped a friend optimize his application.  His two biggest
  4. problems were slowness when resizing windows and when scrolling.  He
  5. had identified the slow methods; I came up with the following
  6. changes to CPane.c to speed things up.
  7.  
  8. I don't guarantee that these changes are free of negative side
  9. effects, but they dramatically increased the performance of his application
  10. with large documents.
  11.  
  12. I'm also aware that further improvements along these lines may be
  13. possible.  Sorry, but I only have time to work on things that demand
  14. attention right now...
  15.  
  16. I encourage you to examine the changes skeptically and let me know if
  17. you have problems.
  18.  
  19.     Doug Wyatt, 7/31/90 (CIS: 76004,2156)
  20.  
  21. ======================================================================================
  22.  
  23.  
  24. #1. Window changing size sends ChangeSize to all panes in window.  SLOW.
  25.     Why?  CalcAperture is visiting all subpanes.  Since a pane's aperture
  26.     is a function of its enclosure's aperture and its frame, subpanes'
  27.     apertures only need recalculation when their enclosure's aperture
  28.     changes.
  29.  
  30.  
  31. /*
  32.     CPane::CalcAperture
  33.     
  34.     Improvement: Don't ask subviews to recalculate their apertures if the pane's
  35.     aperture didn't change.
  36. */
  37. void    CPane::CalcAperture()
  38. {
  39.     Rect        enclAperture;            /* Aperture of pane's enclosure        */
  40.     Rect        prevAperture;
  41.     
  42.     prevAperture = aperture;
  43.                                         /* Get enclosure's aperture            */
  44.     itsEnclosure->GetAperture(&enclAperture);
  45.     EnclToFrameR(&enclAperture);        /* Convert it to Frame coords        */
  46.     
  47.                                         /* Aperture is the frame restricted    */
  48.                                         /*   by the enclosure's aperture    */
  49.     SectRect(&frame, &enclAperture, &aperture);
  50.     
  51.     if (!EqualRect(&prevAperture, &aperture) && itsSubviews != NULL)    /* dsw 7/30/90 */
  52.         itsSubviews->DoForEach(Pane_CalcAperture);  /* Pass it on to subviews   */
  53. }
  54.  
  55. ==================================================================================================
  56.  
  57. #2. Scrolling is slow.  The problem is that Offset calls CalcAperture
  58.     for every subpane of every subpane (...) in the window, despite
  59.     the first optimization.  
  60.  
  61.     This, in effect, applies the same optimization to Offset, but the
  62.     implementation is slightly complicated.  Offset now records whether
  63.     the pane's aperture has changed, and then Pane_EnclosureMoved
  64.     looks at this to decide whether to bother recalculating the subpane's
  65.     aperture.
  66.  
  67.  
  68. /*
  69.     Pane_SimpleCalcAperture
  70.     
  71.     Just like CalcAperture, except:
  72.     Say whether the aperture changed.  Don't visit subviews.
  73.     Used by improved Offset().
  74.     
  75.     Could be a method if you don't mind recompiling.  It's just as fast
  76.     (though less readable) this way.
  77. */
  78. static Boolean Pane_SimpleCalcAperture(register CPane *pane);    /* prototype */
  79. static Boolean Pane_SimpleCalcAperture(register CPane *pane)
  80. {
  81.     Rect        enclAperture;            /* Aperture of pane's enclosure        */
  82.     Rect        prevAperture;
  83.     
  84.     prevAperture = pane->aperture;
  85.                                         /* Get enclosure's aperture            */
  86.     pane->itsEnclosure->GetAperture(&enclAperture);
  87.     pane->EnclToFrameR(&enclAperture);        /* Convert it to Frame coords        */
  88.     
  89.                                         /* Aperture is the frame restricted    */
  90.                                         /*   by the enclosure's aperture    */
  91.     SectRect(&pane->frame, &enclAperture, &pane->aperture);
  92.     
  93.     return ( !EqualRect(&prevAperture, &pane->aperture) );
  94. }
  95.  
  96. /******************************************************************************
  97.  Offset
  98.  
  99.         Translate the location of the Pane within its enclosure
  100.  ******************************************************************************/
  101. typedef struct {
  102.     Point    offset;
  103.     Boolean    enclosureApertureChanged;
  104. } OffsetInfo;
  105.  
  106.         /*
  107.          * Tell a Pane that its enclosure has moved. Send Offset message
  108.          * with redraw set to FALSE, since enclosure will have already
  109.          * taken care of adding the appropriate areas to the update region.
  110.          */
  111.          static void    Pane_EnclosureMoved(
  112.              register CPane    *thePane,
  113.              OffsetInfo        *moveInfo)
  114.          {
  115.              /* Instead of recursing into Offset, replicate relevant code */
  116.              /* Don't need to refresh */
  117.              
  118.             thePane->hOrigin -= moveInfo->offset.h;    /* Change location of the pane    */
  119.             thePane->vOrigin -= moveInfo->offset.v;
  120.              /*    Only need to CalcAperture if its OUTERMOST MOVED enclosure's 
  121.                  aperture was changed.  (Actually, if THIS pane's enclosure's
  122.                  aperture hadn't changed, that would be reason not to
  123.                  recalculate; but for simplicity, we're just covering the grossest
  124.                  case of a panorama with hundreds of panes being offset during
  125.                  scrolling, and most of their apertures not changing). */
  126.              if (moveInfo->enclosureApertureChanged)
  127.                  Pane_SimpleCalcAperture(thePane);
  128.              if (thePane->itsSubviews)
  129.                  thePane->itsSubviews->DoForEach1(Pane_EnclosureMoved, (long)moveInfo);
  130.          }
  131.          
  132. void    CPane::Offset(
  133.     short        hOffset,                /* Pixels to offset horizontally    */
  134.     short        vOffset,                /* Pixels to offset vertically        */
  135.     Boolean        redraw)                    /* Redraw Pane or not?                */
  136. {
  137.     OffsetInfo moveInfo;
  138.     
  139.     if (redraw) {
  140.         Refresh();                        /* Force redraw of area covered by    */
  141.     }                                    /*   current location of pane        */
  142.  
  143.     hOrigin -= hOffset;                    /* Change location of the pane        */
  144.     vOrigin -= vOffset;
  145.     
  146.     moveInfo.enclosureApertureChanged = Pane_SimpleCalcAperture(this);
  147.                                         /* Visible portion of pane could    */
  148.                                         /*   change as a result of a shift    */
  149.                                         /*   in its location                */
  150.     
  151.     if (redraw) {                                    
  152.         Refresh();                        /* Redraw pane at its new location    */
  153.     }
  154.     
  155.     if (itsSubviews != NULL) {            /* Inform subviews of the move        */
  156.         moveInfo.offset.h = hOffset;    /*   so they can adjust their        */
  157.         moveInfo.offset.v = vOffset;    /*   locations                        */
  158.         itsSubviews->DoForEach1(Pane_EnclosureMoved, (long) &moveInfo);
  159.     }
  160. }
  161.  
  162.